#include "texts.h"
/* vim:ts=4:sw=4:noet
 * (tabspace=4)
 * 
 * Copyright (C) 2004, 2005 Walter Doekes, <walter@djcvt.net>.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef _WIN32
#	define WINDOWS_LEAN_AND_MEAN
#	include <windows.h>
#else /* !_WIN32 */
#	include <stdio.h>
#	include <string.h>
#	include <errno.h>
#endif /* !_WIN32 */
#include <assert.h>

static int last_error = 0;
static int last_error_os = 0;
static const char* last_error_context = 0;
static char last_error_buf[512];

static const char* texts[] = {
	/* BASE32_INVALID_CHARACTER */
	"Invalid character encountered in BASE32 stream",
	/* ESCAPE_INVALID_ESCAPE */
	"Invalid escape sequence encountered",
	/* TEXTS_UNKNOWN_ERROR */
	"Unknown error",
	/* THEX_INVALID_BLOCK_SIZE */
	"The read operation isn't supplying multiples of 1024",
	/* TTHSUM_FILENAME_TOO_LARGE */
	"File name is too long",
	/* TTHSUM_LINE_CORRUPT */
	"Improperly formatted line",
	/* TTHSUM_MISMATCHED_TTH */
	"TTH check failed for",
	/* UTF8_INVALID_UNICODE */
	"Invalid character encountered in UNICODE stream",
	/* UTF8_INVALID_UTF8 */
	"Invalid character encountered in UTF8 stream"
};

void set_error(char const* context, int error) {
	assert(strlen(context) < 32);
	if(error == -1) {
#ifdef _WIN32
		last_error = GetLastError();
#else /* !_WIN32 */
		last_error = errno;
#endif /* !_WIN32 */
		last_error_os = 1;
	} else {
		last_error = error;
		last_error_os = 0;
	}
	last_error_context = context;
}

const char* get_error() {
	if(last_error == 0) {
		return NULL;
	} else if(!last_error_os) {
		return texts[last_error];
	} else {
#ifdef _WIN32
		DWORD w;
		int i;
		i = sprintf(last_error_buf, "%s: ", last_error_context);
		if((w = FormatMessage(
				FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
				NULL, (DWORD)last_error, 0, last_error_buf + i, 480 - i, NULL)
		) != 0) { /* 32 is enough for " (int)" */
			if(w >= 2)
				sprintf(last_error_buf + i + w - 2, " (0x%x)", last_error);
		} else {
			sprintf(last_error_buf + i, ": %s (0x%x)",
					get_text(TEXTS_UNKNOWN_ERROR), (unsigned)last_error);
		}
#else /* !_WIN32 */
		snprintf(last_error_buf, 511, "%s: %s (%i)", last_error_context,
				strerror(last_error), last_error);
#endif /* !_WIN32 */
		return last_error_buf;
	}
}

const char* get_text(enum text_id id) {
	return texts[id];
}
